/**
 * Copyright (c) 2016-2020 https://github.com/zhaohuatai
 *
 * contact 824069438@qq.com
 *  
 */
package org.zfes.snowy.auth.shiro.weichat.auhec;

import java.util.LinkedHashMap;
import java.util.Optional;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;
import org.zfes.snowy.auth.AuthConsts;
import org.zfes.snowy.auth.shiro.filter.authc.SnowyTokenAuthenticationFilter;
import org.zfes.snowy.auth.shiro.suser.SessionUser;
import org.zfes.snowy.auth.shiro.suser.SessionUserManager;
import org.zfes.snowy.auth.shiro.weichat.token.WeiChatAuthToken;
import org.zfes.snowy.core.util.AppCtxUtil;
import org.zfes.snowy.core.util.ZStrUtil;

import com.alibaba.fastjson.JSONObject;
public  class SnowyWeiChatAuthenticationFilter extends SnowyTokenAuthenticationFilter{
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	/**
	 *\/api/auth/weichat/auth/callback
	 */
	protected String weiChatAuthCallbackUrl = AuthConsts.LOGIN.DEFAULT_LOGIN_WEICHAT_WEICHAT_AUTH_CALLBACK_URL;
	private String weiChatAppid;
	private String weiChatSecret;
	 	@Autowired  
	    private RestTemplate restTemplate;
		@Autowired
		private SessionUserManager sessionUserManager;
		
	   	@Override
	   	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
	   		if(isWeiChatAuthCallback( request,  response)) {
	   			return executeLogin( request,  response) ;
	   		}
	   		authecUnAuthecHandler.onAuthenticationUnAuthec(WebUtils.toHttp(request), WebUtils.toHttp(response));
	   		return false;
	   	}
	   	
		protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
			String code=request.getParameter("code");
	    	logger.debug("code:||"+code);
	    	System.out.println("code:||"+code);
	    	//String url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx69363f145b06ea8f&secret=43a9861de5368024fc4b3654c344c13a&code="+code+"&grant_type=authorization_code";
	    	String url="https://api.weixin.qq.com/sns/oauth2/access_token?appid="+weiChatAppid+"&secret="+weiChatSecret+"&code="+code+"&grant_type=authorization_code";
	    	
	    	logger.debug("url:||"+url);
	         JSONObject result=getRestTemplate().getForObject(url, JSONObject.class, new LinkedHashMap<>());
	         logger.debug("result:||"+result);
	         System.out.println("result:||"+result);
	         if(ZStrUtil.hasText(result.getString("errcode"))) {//
	        	 authecFailureHandler.onAuthenticationFailure(WebUtils.toHttp(request), WebUtils.toHttp(response), result.getString("errcode"));
	        	 return false;
	         }
	         String access_token=result.getString("access_token");
	         String openid=result.getString("openid");
	         logger.debug("access_token:"+access_token+"||openid:"+openid);
	         System.out.println("access_token:"+access_token+"||openid:"+openid);
	         
//	        String url2="https://api.weixin.qq.com/sns/userinfo?access_token="+access_token+"&openid="+openid+"&lang=zh_CN";
//	         JSONObject result2=getRestTemplate().getForObject(url2, JSONObject.class, new LinkedHashMap<>());
//	         if(ZStrUtil.hasText(result2.getString("errcode"))) {//
//	        	 ZAlert.serviceLogicalError(result2.getString("errmsg"));
//	         }
//	         logger.debug("result2:||"+result2);
			//String openid="o_ZQ4wH7dvPq1ovhfCbNqKXyGc_Y";
	        try {
	        	 Subject subject = getSubject(request, response);
	        	 Session session=subject.getSession();
	        	 System.out.println("executeLogin--sessionid:"+session.getId());
		         Optional<SessionUser> sessionUserOp =  getSessionUserManager().loadSessionUserByOpenId(openid);
		         SessionUser sessionUser=sessionUserOp.orElse(new SessionUser());
		         if(sessionUserOp.isPresent()) {
		        	 logger.debug("已经注册");
		        	 System.out.println("已经注册");
			         
		        	 try {
		        		 SecurityUtils.getSubject().login(new WeiChatAuthToken(sessionUserOp.get().getUsername(),"anonymous".toCharArray()));
		        	 }catch (AuthenticationException e) {
		        		 logger.error(e.getMessage());
		        		 System.out.println("登录失败"+e.getMessage());
		        		 authecFailureHandler.onAuthenticationFailure(WebUtils.toHttp(request), WebUtils.toHttp(response),e);
		        		 return false;
					}
		        	 System.out.println("登录成功");
		        	
		        	 //sessionUser.setAuthLevel(2);
		        	 sessionUser.setOpenId(openid);
		        	 System.out.println("sessionUser："+sessionUser);
		         }else {
		        	 logger.debug("没有注册");
		        	 System.out.println("没有注册");
		        	 try {
		        		 subject.login(new WeiChatAuthToken("anonymous","anonymous".toCharArray()));
		        	 }catch (AuthenticationException e) {
		        		 logger.error(e.getMessage());
		        		 authecFailureHandler.onAuthenticationFailure(WebUtils.toHttp(request), WebUtils.toHttp(response),e);
		        		 return false;
					}
		        	 sessionUser.setAuthLevel(0);
		        	 sessionUser.setOpenId(openid);
		        	 sessionUser.setUsername("anonymous");
		        	 System.out.println("sessionUser:"+sessionUser);
		         }
//		        if(isEnableSessionStrategy&&maxSession!=null&&maxSession>0){
//		            MultiLoginLimitUtil.validateSessionLimit(subject, maxSession);
//		        }
		       
		        session.setAttribute(AuthConsts.SESSION.SESSION_USER_KEY,sessionUser);
		        session.setAttribute(AuthConsts.SESSION.SESSION_LOGINORGIN_KEY, "WEICHAT");
		        WebUtils.redirectToSavedRequest(request, response, "/index.html#/registervip");
		       // authecSuccessHandler.onAuthenticationSuccess(WebUtils.toHttp(request), WebUtils.toHttp(response), subject,getIsEnableCSRFToken());
	        } catch (AuthenticationException exception) {
	        	authecFailureHandler.onAuthenticationFailure(WebUtils.toHttp(request), WebUtils.toHttp(response), exception);
	        }
	        return false;
	    }  
	    
	  //----------------------------------------createToken----------------------------------------------------------------------------
      protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
          String username = getUsername(request);
          String password = getPassword(request);
          return createToken(username, password, request, response);
      }
      
      protected AuthenticationToken createToken(String username, String password,ServletRequest request, ServletResponse response) {
  			boolean rememberMe =isRememberMe(request);
  			String host = getHost(request);
  			return createToken(username, password, rememberMe, host);
  	   }
      protected AuthenticationToken createToken(String username, String password,boolean rememberMe, String host) {
      	return new UsernamePasswordToken(username, password, rememberMe, host);
      }

	public String getWeiChatAuthCallbackUrl() {
		return weiChatAuthCallbackUrl;
	}

	public void setWeiChatAuthCallbackUrl(String weiChatAuthCallbackUrl) {
		this.weiChatAuthCallbackUrl = weiChatAuthCallbackUrl;
	}
    private boolean isWeiChatAuthCallback(ServletRequest request, ServletResponse response) {
			 return pathsMatch( getWeiChatAuthCallbackUrl() ,  request);
		}

	public RestTemplate getRestTemplate() {
		if(restTemplate==null) {
			restTemplate=AppCtxUtil.getBean(RestTemplate.class);
		}
		return restTemplate;
	}

	public void setRestTemplate(RestTemplate restTemplate) {
		this.restTemplate = restTemplate;
	}

	public SessionUserManager getSessionUserManager() {
		if(sessionUserManager==null) {
			sessionUserManager=AppCtxUtil.getBean("sessionUserManagerImpl");
		}
		return sessionUserManager;
	}

	public void setSessionUserManager(SessionUserManager sessionUserManager) {
		this.sessionUserManager = sessionUserManager;
	}

	public String getWeiChatAppid() {
		return weiChatAppid;
	}

	public void setWeiChatAppid(String weiChatAppid) {
		this.weiChatAppid = weiChatAppid;
	}

	public String getWeiChatSecret() {
		return weiChatSecret;
	}

	public void setWeiChatSecret(String weiChatSecret) {
		this.weiChatSecret = weiChatSecret;
	}
      
    
}
